{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# A Simple Neural Network Making a Prediction"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### What is a Neural Network?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.8500000000000001\n"
     ]
    }
   ],
   "source": [
    "# The network:\n",
    "\n",
    "weight = 0.1 \n",
    "def neural_network(input, weight):\n",
    "    prediction = input * weight\n",
    "    return prediction\n",
    "\n",
    "# How we use the network to predict something:\n",
    "\n",
    "number_of_toes = [8.5, 9.5, 10, 9]\n",
    "input = number_of_toes[0]\n",
    "pred = neural_network(input,weight)\n",
    "print(pred)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Making a Prediction with Multiple Inputs"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Complete Runnable Code"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.9800000000000001\n"
     ]
    }
   ],
   "source": [
    "def w_sum(a,b):\n",
    "    assert(len(a) == len(b))\n",
    "    output = 0\n",
    "    for i in range(len(a)):\n",
    "        output += (a[i] * b[i])\n",
    "    return output\n",
    "\n",
    "weights = [0.1, 0.2, 0] \n",
    "    \n",
    "def neural_network(input, weights):\n",
    "    pred = w_sum(input,weights)\n",
    "    return pred\n",
    "\n",
    "# This dataset is the current\n",
    "# status at the beginning of\n",
    "# each game for the first 4 games\n",
    "# in a season.\n",
    "\n",
    "# toes = current number of toes\n",
    "# wlrec = current games won (percent)\n",
    "# nfans = fan count (in millions)\n",
    "\n",
    "toes =  [8.5, 9.5, 9.9, 9.0]\n",
    "wlrec = [0.65, 0.8, 0.8, 0.9]\n",
    "nfans = [1.2, 1.3, 0.5, 1.0]\n",
    "\n",
    "# Input corresponds to every entry\n",
    "# for the first game of the season.\n",
    "\n",
    "input = [toes[0],wlrec[0],nfans[0]]\n",
    "pred = neural_network(input,weights)\n",
    "\n",
    "print(pred)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### NumPy Code"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.9800000000000001\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "weights = np.array([0.1, 0.2, 0])\n",
    "def neural_network(input, weights):\n",
    "    pred = input.dot(weights)\n",
    "    return pred\n",
    "    \n",
    "toes =  np.array([8.5, 9.5, 9.9, 9.0])\n",
    "wlrec = np.array([0.65, 0.8, 0.8, 0.9])\n",
    "nfans = np.array([1.2, 1.3, 0.5, 1.0])\n",
    "\n",
    "# Input corresponds to every entry\n",
    "# for the first game of the season.\n",
    "\n",
    "input = np.array([toes[0],wlrec[0],nfans[0]])\n",
    "pred = neural_network(input,weights)\n",
    "\n",
    "print(pred)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Making a Prediction with Multiple Outputs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0.195, 0.13, 0.5850000000000001]\n"
     ]
    }
   ],
   "source": [
    "# Instead of predicting just \n",
    "# whether the team won or lost, \n",
    "# now we're also predicting whether\n",
    "# they are happy/sad AND the percentage\n",
    "# of the team that is hurt. We are\n",
    "# making this prediction using only\n",
    "# the current win/loss record.\n",
    "\n",
    "def ele_mul(number,vector):\n",
    "    output = [0,0,0]\n",
    "    assert(len(output) == len(vector))\n",
    "    for i in range(len(vector)):\n",
    "        output[i] = number * vector[i]\n",
    "    return output\n",
    "\n",
    "weights = [0.3, 0.2, 0.9] \n",
    "\n",
    "def neural_network(input, weights):\n",
    "    pred = ele_mul(input,weights)\n",
    "    return pred\n",
    "    \n",
    "wlrec = [0.65, 0.8, 0.8, 0.9]\n",
    "input = wlrec[0]\n",
    "pred = neural_network(input,weights)\n",
    "\n",
    "print(pred)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Predicting with Multiple Inputs & Outputs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0.555, 0.9800000000000001, 0.9650000000000001]\n"
     ]
    }
   ],
   "source": [
    "            #toes %win #fans\n",
    "weights = [ [0.1, 0.1, -0.3], #hurt?\n",
    "            [0.1, 0.2, 0.0], #win?\n",
    "            [0.0, 1.3, 0.1] ] #sad?\n",
    "\n",
    "def w_sum(a,b):\n",
    "    assert(len(a) == len(b))\n",
    "    output = 0\n",
    "    for i in range(len(a)):\n",
    "        output += (a[i] * b[i])\n",
    "    return output\n",
    "\n",
    "def vect_mat_mul(vect,matrix):\n",
    "    assert(len(vect) == len(matrix))\n",
    "    output = [0,0,0]\n",
    "    for i in range(len(vect)):\n",
    "        output[i] = w_sum(vect,matrix[i])\n",
    "    return output\n",
    "\n",
    "def neural_network(input, weights):\n",
    "    pred = vect_mat_mul(input,weights)\n",
    "    return pred\n",
    "\n",
    "# This dataset is the current\n",
    "# status at the beginning of\n",
    "# each game for the first 4 games\n",
    "# in a season.\n",
    "\n",
    "# toes = current number of toes\n",
    "# wlrec = current games won (percent)\n",
    "# nfans = fan count (in millions)\n",
    "\n",
    "toes =  [8.5, 9.5, 9.9, 9.0]\n",
    "wlrec = [0.65,0.8, 0.8, 0.9]\n",
    "nfans = [1.2, 1.3, 0.5, 1.0]\n",
    "\n",
    "# Input corresponds to every entry\n",
    "# for the first game of the season.\n",
    "\n",
    "input = [toes[0],wlrec[0],nfans[0]]\n",
    "pred = neural_network(input,weights)\n",
    "\n",
    "print(pred)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Predicting on Predictions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0.21350000000000002, 0.14500000000000002, 0.5065]\n"
     ]
    }
   ],
   "source": [
    "            #toes %win #fans\n",
    "ih_wgt = [ [0.1, 0.2, -0.1], #hid[0]\n",
    "           [-0.1,0.1, 0.9], #hid[1]\n",
    "           [0.1, 0.4, 0.1] ] #hid[2]\n",
    "\n",
    "           #hid[0] hid[1] hid[2]\n",
    "hp_wgt = [ [0.3, 1.1, -0.3], #hurt?\n",
    "           [0.1, 0.2, 0.0], #win?\n",
    "           [0.0, 1.3, 0.1] ] #sad?\n",
    "\n",
    "weights = [ih_wgt, hp_wgt]\n",
    "\n",
    "def neural_network(input, weights):\n",
    "    hid = vect_mat_mul(input,weights[0])\n",
    "    pred = vect_mat_mul(hid,weights[1])\n",
    "    return pred\n",
    "\n",
    "toes =  [8.5, 9.5, 9.9, 9.0]\n",
    "wlrec = [0.65,0.8, 0.8, 0.9]\n",
    "nfans = [1.2, 1.3, 0.5, 1.0]\n",
    "\n",
    "# Input corresponds to every entry\n",
    "# for the first game of the season.\n",
    "\n",
    "input = [toes[0],wlrec[0],nfans[0]]\n",
    "pred = neural_network(input,weights)\n",
    "\n",
    "print(pred)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# NumPy Version"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0.2135 0.145  0.5065]\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "\n",
    "#toes %win #fans\n",
    "ih_wgt = np.array([ \n",
    "            [0.1, 0.2, -0.1], #hid[0]\n",
    "            [-0.1,0.1, 0.9], #hid[1]\n",
    "            [0.1, 0.4, 0.1]]).T #hid[2]\n",
    "\n",
    "\n",
    "# hid[0] hid[1] hid[2]\n",
    "hp_wgt = np.array([  \n",
    "            [0.3, 1.1, -0.3], #hurt?\n",
    "            [0.1, 0.2, 0.0], #win?\n",
    "            [0.0, 1.3, 0.1] ]).T #sad?\n",
    "\n",
    "weights = [ih_wgt, hp_wgt]\n",
    "\n",
    "def neural_network(input, weights):\n",
    "\n",
    "    hid = input.dot(weights[0])\n",
    "    pred = hid.dot(weights[1])\n",
    "    return pred\n",
    "\n",
    "\n",
    "toes =  np.array([8.5, 9.5, 9.9, 9.0])\n",
    "wlrec = np.array([0.65,0.8, 0.8, 0.9])\n",
    "nfans = np.array([1.2, 1.3, 0.5, 1.0])\n",
    "\n",
    "input = np.array([toes[0],wlrec[0],nfans[0]])\n",
    "\n",
    "pred = neural_network(input,weights)\n",
    "print(pred)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# A Quick Primer on NumPy"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0 1 2 3]\n",
      "[4 5 6 7]\n",
      "[[0 1 2 3]\n",
      " [4 5 6 7]]\n",
      "[[0. 0. 0. 0.]\n",
      " [0. 0. 0. 0.]]\n",
      "[[0.40221396 0.5714968  0.68579318 0.73326444 0.42793703]\n",
      " [0.19555759 0.20401945 0.21708259 0.95738529 0.42907317]]\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "\n",
    "a = np.array([0,1,2,3]) # a vector\n",
    "b = np.array([4,5,6,7]) # another vector\n",
    "c = np.array([[0,1,2,3], # a matrix\n",
    "              [4,5,6,7]])\n",
    "\n",
    "d = np.zeros((2,4)) # (2x4 matrix of zeros)\n",
    "e = np.random.rand(2,5) # random 2x5\n",
    "# matrix with all numbers between 0 and 1\n",
    "\n",
    "print(a)\n",
    "print(b)\n",
    "print(c)\n",
    "print(d)\n",
    "print(e)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0. 0. 0. 0.]]\n",
      "[[0. 0. 0.]]\n"
     ]
    },
    {
     "ename": "ValueError",
     "evalue": "operands could not be broadcast together with shapes (1,4) (4,3) ",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mValueError\u001b[0m                                Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-11-7608a210c62a>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m      3\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mc\u001b[0m \u001b[0;34m*\u001b[0m \u001b[0;36m0.2\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# multiplies every number in matrix \"c\" by 0.2\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      4\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 5\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m \u001b[0;34m*\u001b[0m \u001b[0mb\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# multiplies elementwise between a and b (columns paired up)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m      6\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      7\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m \u001b[0;34m*\u001b[0m \u001b[0mb\u001b[0m \u001b[0;34m*\u001b[0m \u001b[0;36m0.2\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# elementwise multiplication then multiplied by 0.2\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mValueError\u001b[0m: operands could not be broadcast together with shapes (1,4) (4,3) "
     ]
    }
   ],
   "source": [
    "print(a * 0.1) # multiplies every number in vector \"a\" by 0.1\n",
    "      \n",
    "print(c * 0.2) # multiplies every number in matrix \"c\" by 0.2\n",
    "      \n",
    "print(a * b) # multiplies elementwise between a and b (columns paired up)\n",
    "      \n",
    "print(a * b * 0.2) # elementwise multiplication then multiplied by 0.2\n",
    "      \n",
    "print(a * c) # since c has the same number of columns as a, this performs\n",
    "# elementwise multiplication on every row of the matrix \"c\"\n",
    "\n",
    "print(a * e) # since a and e don't have the same number of columns, this\n",
    "# throws a \"Value Error: operands could not be broadcast together with..\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(1, 3)\n"
     ]
    }
   ],
   "source": [
    "a = np.zeros((1,4)) # vector of length 4\n",
    "b = np.zeros((4,3)) # matrix with 4 rows & 3 columns\n",
    "\n",
    "c = a.dot(b)\n",
    "print(c.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(2, 3)\n",
      "(2, 3)\n",
      "(4, 6)\n"
     ]
    },
    {
     "ename": "ValueError",
     "evalue": "shapes (5,4) and (5,6) not aligned: 4 (dim 1) != 5 (dim 0)",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mValueError\u001b[0m                                Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-13-37331c0fca7f>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m     19\u001b[0m \u001b[0mh\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mzeros\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m5\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m4\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# matrix with 5 rows and 4 columns\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     20\u001b[0m \u001b[0mi\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mzeros\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m5\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m6\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# matrix with 5 rows & 6 columns\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 21\u001b[0;31m \u001b[0mj\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mh\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdot\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mi\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     22\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mj\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mshape\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# throws an error\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mValueError\u001b[0m: shapes (5,4) and (5,6) not aligned: 4 (dim 1) != 5 (dim 0)"
     ]
    }
   ],
   "source": [
    "a = np.zeros((2,4)) # matrix with 2 rows and 4 columns\n",
    "b = np.zeros((4,3)) # matrix with 4 rows & 3 columns\n",
    "\n",
    "c = a.dot(b)\n",
    "print(c.shape) # outputs (2,3)\n",
    "\n",
    "e = np.zeros((2,1)) # matrix with 2 rows and 1 columns\n",
    "f = np.zeros((1,3)) # matrix with 1 row & 3 columns\n",
    "\n",
    "g = e.dot(f)\n",
    "print(g.shape) # outputs (2,3)\n",
    "\n",
    "h = np.zeros((5,4)).T # matrix with 4 rows and 5 columns\n",
    "i = np.zeros((5,6)) # matrix with 6 rows & 5 columns\n",
    "\n",
    "j = h.dot(i)\n",
    "print(j.shape) # outputs (4,6)\n",
    "\n",
    "h = np.zeros((5,4)) # matrix with 5 rows and 4 columns\n",
    "i = np.zeros((5,6)) # matrix with 5 rows & 6 columns\n",
    "j = h.dot(i)\n",
    "print(j.shape) # throws an error"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
